﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.IO;
using System.Windows.Controls;
using System.Windows.Input;
using System.ComponentModel;
using System.Media;
using StandardScriptItems;
using Tedds_Tool.Automatables;
using GUI.Custom_Classes;
using Tedds_Tool;

namespace LEET.Application.Custom_Classes
{
    public abstract class CreateRulePart : Window
    {
        #region Attributes

        private int numsVer;
        private ScriptViewer selected;
        protected IScriptFinder scriptFinder;
        private double prev_scroll = 0;
        protected ILEETFactory factory;

        #endregion

        /// <summary>
        /// Class constructor for window to create a new precondition.
        /// </summary>
        /// <param name="m">The current automation element targeted by the main program.</param>
        /// <param name="sv">The list of currently selected script lines in ScriptViewer</param>
        /// <param name="iList"></param>
        //public CreatePrecond(AutomationElement m, IList iList)
        public CreateRulePart() { }
        public CreateRulePart(ILEETFactory factory, IScript sv, IScriptFinder scriptFinder)
        {
            FrameworkElement ele = sv as FrameworkElement;
            while (!(ele is Window))
                ele = ele.Parent as FrameworkElement;
            Owner = ele as Window;
            this.factory = factory;
            this.scriptFinder = scriptFinder;
            numsVer = 0;
            selected = sv as ScriptViewer;
            this.KeyDown += new KeyEventHandler(removeVerify);
        }

        
        #region Button & ComboBox Events

        /// <summary>
        /// Adds a new verify statement for manual interaction.
        /// </summary>
        public void addVerify(object sender, RoutedEventArgs e)
        {
            if (numsVer < 0)
                numsVer = 0;

            IScriptBuilder newVer = factory.CreateScriptBuilder() as IScriptBuilder;
            newVer.Filter(delegate(String str) { return (str.StartsWith("--") && str.EndsWith("--")) || str.Equals("VERIFY"); });
            Label l = new Label();

            newVer.Name = NamePrefix + BuildPanel.Items.Count;

            l.Height = 24;
            l.Width = 60;
            l.VerticalContentAlignment = System.Windows.VerticalAlignment.Center;
            l.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Left;
            l.Content = ItemLabel + "__" + numsVer + ":";

            LPanel.Children.Add(l);
            BuildPanel.Items.Add(newVer);
            numsVer++;
        }

        /// <summary>
        /// Closes the dialog window without creating file.
        /// </summary>
        public void cancel_Button(object sender, RoutedEventArgs e)
        {
            Close();
        }

        public void cancel_Button(object sender, CancelEventArgs e)
        {
            //Close();
        }

        /// <summary>
        /// Creates a precondition file for the list statements.
        /// </summary>
        public void createVerify(object sender, RoutedEventArgs e)
        {
            if (String.IsNullOrEmpty(NameBox.Text))
            {
                SystemSounds.Beep.Play();
                MessageBox.Show(Owner, "You must specify a name for the action.", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
            }
            //else if (TargetBox.SelectedIndex == 0)
            //{
            //    SystemSounds.Beep.Play();
            //    MessageBox.Show(Owner, "Specify target element(s), all or specific.", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
            //}
            else
            {
                String scriptName = NameBox.Text;
                BuildPanel.Dispatcher.Invoke
                (
                    (Action)(() =>
                    {
                        TextWriter sw = null;
                        try
                        {
                            sw = GetWriter(scriptName);
                            string s;
                            for (int i = 0; i < BuildPanel.Items.Count; i++)
                            {
                                if (BuildPanel.Items.GetItemAt(i) is ScriptBuilder)
                                    s = ((ScriptBuilder)BuildPanel.Items.GetItemAt(i)).ToString();
                                else
                                    s = ((TextBox)BuildPanel.Items.GetItemAt(i)).ToString();

                                if (s.Contains("System.Windows.Controls.TextBox: "))
                                    s = s.Remove(0, "System.Windows.Controls.TextBox: ".Length);
                                sw.WriteLine(s);
                            }
                            MessageBox.Show(Owner, RulePartType + " saved successfully.", "Save Complete", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);
                        }
                        finally
                        {
                            sw.Dispose();
                        }
                    }
                ));
                Close();
            }
        }

        /// <summary>
        /// Adds the selected verify statements in list of selected items from the scriptviewer.
        /// </summary>
        public void addSelectedVerify(object sender, RoutedEventArgs e)
        {
            if (numsVer < 0)
                numsVer = 0;

            List<TextBox> ordered = new List<TextBox>();

            for (int i = 0; i < selected.Items.Count; ++i)
            {
                if (selected.SelectedItems.Contains(selected.Items[i]))
                {
                    String text = selected.Items[i].ToString();
                    if (text.Contains("System.Windows.Controls.TextBox: "))
                        text = selected.Items[i].ToString().Remove(0, "System.Windows.Controls.TextBox: ".Length);
                    ordered.Add(new TextBox { Text = text });
                }
            }
            selected.UnselectAll();

            for (int i = 0; i < ordered.Count; i++)
            {
                if (!((TextBox)ordered[i]).Text.StartsWith("VERIFY"))
                    continue;

                TextBox newVer = new TextBox();
                Label l = new Label();

                newVer.Text = ((TextBox)ordered[i]).Text;
                newVer.Height = 24;
                newVer.VerticalAlignment = System.Windows.VerticalAlignment.Center;
                newVer.Name = NamePrefix + BuildPanel.Items.Count;

                l.Height = 24;
                l.Width = 60;
                l.VerticalContentAlignment = System.Windows.VerticalAlignment.Center;
                l.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Left;
                l.Content = ItemLabel + "__" + numsVer + ":";

                LPanel.Children.Add(l);
                BuildPanel.Items.Add(newVer);
                numsVer++;
            }
        }

        /// <summary>
        /// Removes the selected preconditions from the list.
        /// </summary>
        public void removeVerify(object sender, RoutedEventArgs args)
        {
            if (args is KeyEventArgs)
            {
                KeyEventArgs kargs = args as KeyEventArgs;
                if (kargs.Key.CompareTo(Key.Delete) != 0)
                    return;
            }

            while (BuildPanel.SelectedItems.Count > 0)
            {
                BuildPanel.Items.Remove(BuildPanel.SelectedItem);
                LPanel.Children.RemoveAt(LPanel.Children.Count - 1);
                numsVer--;
            }

            ScriptBuilder sb = null;
            for (int i = 0; i < BuildPanel.Items.Count; i++)
            {
                sb = ((ScriptBuilder)BuildPanel.Items.GetItemAt(i));
                sb.Name = NamePrefix + i;
            }

            Focus();
        }

        #endregion

        #region Helper Functions

        /// <summary>
        /// Deselects the background in the viewing pane.
        /// </summary>
        public void Unselect_Background(object sender, SelectionChangedEventArgs e)
        {
            BuildPanel.UnselectAll();
        }

        /// <summary>
        /// Enables checking preconditions against all available targets.
        /// </summary>
        public void targetBoxChanged(object sender, SelectionChangedEventArgs e)
        {
            //if (targetBox.SelectedIndex == 1)
            //    buildPanel.IsEnabled = false;
            //else if (targetBox.SelectedIndex == 2)
            //    buildPanel.IsEnabled = true;
            //else if (actionBuild != null)
            //    actionBuild.IsEnabled = true;
        }

        /// <summary>
        /// Keeps the labels and preconditions list synced in the viewing panes.
        /// </summary>
        public void PrecondList_Scroll(object sender, ScrollChangedEventArgs e)
        {
            if (sender == BuildPanel.Parent)
            {
                if (e.VerticalOffset != prev_scroll)
                {
                    prev_scroll = e.VerticalOffset;
                }

                if (BuildPanel.Parent is ScrollViewer)
                    ((ScrollViewer)BuildPanel.Parent).ScrollToVerticalOffset(prev_scroll);
                ((ScrollViewer)LPanel.Parent).ScrollToVerticalOffset(prev_scroll);
            }
        }

        #endregion

        protected abstract TextWriter GetWriter(String name);

        protected abstract string NamePrefix { get; }
        protected abstract string ItemLabel { get; }
        protected abstract string RulePartType { get; }

        public abstract StackPanel LPanel { get; }
        public abstract ListBox BuildPanel { get; }
        public abstract TextBox NameBox { get; }
        //public abstract ComboBox TargetBox { get; }
    }
}
